package cn.robot.board.net;

import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.Base64;
import android.util.Log;

import com.google.gson.Gson;

import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.POST;

public class RbtCloud {
    // private String BASE_URL   = "https://api.future.ink/";
    private String BASE_URL   = "http://api.test.future.ink/";
    // private String Access_key = "替换您的账号";
    // private String SecretKey  = "替换您的账号";
    // private String user_id    = "替换您的账号";
    private String Access_key = "afd5e1cd-21ba-4030-b161-27bbe4a00232";
    private String SecretKey  = "7b37660f64d6";
    private String user_id    = "10040";

    static               SimpleDateFormat sdf;
    private static final String           DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    public RbtCloud() {
        sdf = new SimpleDateFormat(DEFAULT_DATE_FORMAT);
    }

    public void sendPost(String url, String bodyJson, CallBackListener listener) {
        Log.e("setCallback", "url:" + url);
        PostAsyncTask postAsyncTask = new PostAsyncTask();
        postAsyncTask.setBodyJson(bodyJson);
        postAsyncTask.setCallBackListener(listener);
        postAsyncTask.execute(url);
    }

    public void trailsRecog(String strokes, String language, CallBackListener callback) {
        String e = getTimestamp();//时间戳
        Map<String, String> map = new HashMap<>();
        map.put("access_key", Access_key);
        map.put("e", e);
        map.put("is_char", "false");
        map.put("language", language);
        map.put("strokes", strokes);
        map.put("source", "3");
        map.put("sample", "hanzi");
        String method = "POST";
        String url = BASE_URL + "trails/trails/recog";

        Gson gson = new Gson();
        String jsonAll = gson.toJson(map);
        String token = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            token = createToken(method, url, SecretKey, map);
        }
        map.put("token", token);
        Log.d("test", "jsonAll: " + jsonAll);
        sendPost(url, jsonAll, callback);
    }

    private static String getTimestamp() {
        long timestamp = System.currentTimeMillis();
        String timestampStr = String.valueOf(timestamp);
        return timestampStr.substring(0, 10);
    }

    private volatile Mac    macInstance;
    private final    Object LOCK = new Object();

    @RequiresApi(api = Build.VERSION_CODES.N)
    public String createToken(String method, String path, String secretKey, Map<String, String> params) {
        String result = "";
        try {
            path = path.trim();
            secretKey = secretKey.trim();
            // 排序
            List<Map.Entry<String, String>> entries = new ArrayList<>(params.entrySet());
            Collections.sort(entries, new Comparator<Map.Entry<String, String>>() {
                @Override
                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                    return o1.getKey().compareTo(o2.getKey());
                }
            });
            Map<String, String> keyLinked = new LinkedHashMap<>();
            for (Map.Entry<String, String> entry : entries) {
                keyLinked.put(entry.getKey(), entry.getValue());
            }
            // 构造签名键值对的格式
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, String> entry : keyLinked.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                if (value != null && value.trim().length() > 0) {
                    sb.append(key).append("=").append(value).append("&");
                }
            }
            result = sb.substring(0, sb.length() - 1);
            result = URLEncoder.encode(result, "UTF-8");
            String url = URLEncoder.encode(path, "UTF-8");
            String signString = replaceEncode(method + "&" + url + "&" + result);
            String signSecret = secretKey + "&";
            // 对签名做urlencode
            final byte[] sign = sign(signSecret.getBytes("UTF-8"), signString.getBytes("UTF-8"));
            String base64 = new String(Base64.encodeToString(sign, Base64.DEFAULT));
            String token = base64.replaceAll("\\+", "-").replaceAll("\\/", "_");
            return token;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * @param
     * @return
     * @summary 根据key对data数据进行hmacsha1加密
     * @date 2018/12/12 15:12
     */
    private byte[] sign(byte[] key, byte[] data) {
        try {
            if (macInstance == null) {
                synchronized (LOCK) {
                    if (macInstance == null) {
                        macInstance = Mac.getInstance("HmacSHA1");
                    }
                }
            }
            Mac mac;
            try {
                mac = (Mac) macInstance.clone();
            } catch (CloneNotSupportedException e) {
                // If it is not clonable, create a new one.
                mac = Mac.getInstance("HmacSHA1");
            }
            mac.init(new SecretKeySpec(key, "HmacSHA1"));
            return mac.doFinal(data);
        } catch (NoSuchAlgorithmException ex) {
            throw new RuntimeException("Unsupported algorithm: HmacSHA1");
        } catch (InvalidKeyException ex) {
            throw new RuntimeException();
        }
    }

    private String replaceEncode(String encode) {
        return encode.replaceAll("\\+", "%20").replaceAll("\\%21", "!").replaceAll("\\%27", "'")
                .replaceAll("\\%28", "(").replaceAll("\\%29", ")").replaceAll("\\%2A", "*");
    }

    interface Recognition {
        @POST("trails/trails/recog")
        Call<ResponseBody> trailsRecog(@Body RequestBody body);
    }
}
